package com.frontop.terminal.util;

import cn.hutool.core.lang.Console;
import cn.hutool.system.oshi.CpuInfo;
import cn.hutool.system.oshi.OshiUtil;
import com.frontop.terminal.entity.HardDisk;
import com.frontop.terminal.entity.Terminal;
import com.frontop.terminal.rmonclient.encrypt.MD5;
import oshi.SystemInfo;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HWDiskStore;
import oshi.hardware.HWPartition;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.hardware.Sensors;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.FormatUtil;

import java.awt.*;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * <p>
 * 系统性能监控工具
 * </P>
 *
 * @author :CCC
 * @since :2021-05-17 18:12:00
 **/
public class SystemMonitoringUtil {

    /**
     * 获取cpu序列号
     *
     * @return cpu序列号
     */
    public static String getProcessorId() {
        try {
            Process process = Runtime.getRuntime().exec(
                    new String[]{"wmic", "cpu", "get", "ProcessorId"});
            process.getOutputStream().close();
            Scanner sc = new Scanner(process.getInputStream());
            sc.next();
            return sc.next();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取mac
     *
     * @return 网卡mac地址
     */
    public static String getMacAddress() {
        InetAddress ia;
        // 获得网络接口对象（即网卡），并得到mac地址，mac地址存在于一个byte数组中。
        byte[] mac = new byte[0];
        try {
            ia = InetAddress.getLocalHost();
            mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
        } catch (UnknownHostException | SocketException e) {
            e.printStackTrace();
        }

        // 下面代码是把mac地址拼装成String
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < mac.length; i++) {
            if (i != 0) {
                sb.append("-");
            }
            // mac[i] & 0xFF 是为了把byte转化为正整数
            String s = Integer.toHexString(mac[i] & 0xFF);
            sb.append(s.length() == 1 ? 0 + s : s);
        }
        // 把字符串所有小写字母改为大写成为正规的mac地址并返回
        return sb.toString().toUpperCase();
    }

    private static com.frontop.terminal.entity.Sensors getSensors() {
        SystemInfo si = new SystemInfo();
        HardwareAbstractionLayer hal = si.getHardware();
        Sensors sensors = hal.getSensors();
        com.frontop.terminal.entity.Sensors localSensor = new com.frontop.terminal.entity.Sensors();
        localSensor.setCpuTemperature(sensors.getCpuTemperature() + "°C");
        localSensor.setCpuVoltage(sensors.getCpuVoltage() + "V");
        localSensor.setFanSpeeds(Arrays.toString(sensors.getFanSpeeds()));
        return localSensor;
    }

    /**
     * 获取硬盘
     *
     * @return List<HardDisk>
     */
    public static List<HardDisk> getHardDisk() {
        List<HardDisk> hardDiskList = new ArrayList<>();
        SystemInfo si = new SystemInfo();
        OperatingSystem os = si.getOperatingSystem();
        FileSystem fileSystem = os.getFileSystem();

        List<OSFileStore> fsArray = fileSystem.getFileStores();
        for (OSFileStore fs : fsArray) {
            HardDisk hardDisk = new HardDisk();
            hardDisk.setName(fs.getName());
            hardDisk.setPath(fs.getMount());
            hardDisk.setUsableSpace(FormatUtil.formatBytes(fs.getUsableSpace()));
            hardDisk.setSumSpace(FormatUtil.formatBytes(fs.getTotalSpace()));
            String tota = new DecimalFormat("0.00 ").format(100d * fs.getUsableSpace() / fs.getTotalSpace());
            hardDisk.setFreeSpaceRate(tota + "%");
            hardDiskList.add(hardDisk);
        }

        return hardDiskList;
    }

    /**
     * 获取终端对象
     *
     * @return Terminal
     */
    public static Terminal getTerminal() {
        Terminal terminal = new Terminal();
        try {
            //获取cpu信息
            CpuInfo cpuInfo = OshiUtil.getCpuInfo();
            //获取系统信息
            OperatingSystem operatingSystem = OshiUtil.getOs();
            //内存
            GlobalMemory globalMemory = OshiUtil.getMemory();

            terminal.setOs(operatingSystem.getFamily());
            terminal.setOsVersions(operatingSystem.getVersionInfo().getVersion());
            terminal.setOsBits(OshiUtil.getOs().getBitness());
            terminal.setComputerName(System.getenv().get("COMPUTERNAME"));
            terminal.setRunTime(OshiUtil.getOs().getSystemUptime());
            terminal.setCpuLeisureRate(cpuInfo.getFree());
            terminal.setCpuUseRate(cpuInfo.getSys() + cpuInfo.getUsed());
            terminal.setProcessorId(SystemMonitoringUtil.getProcessorId());
            terminal.setCpuInfo(cpuInfo.getCpuModel());
            terminal.setUsableMemory(globalMemory.getAvailable());
            terminal.setSumMemory(globalMemory.getTotal());
            terminal.setIp(InetAddress.getLocalHost().getHostAddress());
            terminal.setMac(SystemMonitoringUtil.getMacAddress());
            terminal.setHardDiskList(SystemMonitoringUtil.getHardDisk());
            terminal.setMachineCode(MD5.encode(terminal.getProcessorId() + terminal.getMac()));
//            terminal.setSensors(getSensors());

            //分辨率
            Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
            int width = (int) screensize.getWidth();
            int height = (int) screensize.getHeight();
            terminal.setScreenSize(width + "x" + height);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return terminal;
    }

    public static void main(String[] args) {
        //获取系统信息
        oshi.software.os.OperatingSystem operatingSystem = OshiUtil.getOs();
        Console.log("操作系统：" + operatingSystem.getFamily());
        Console.log("操作版本：" + operatingSystem.getVersionInfo().getVersion());
        Console.log("操作系统制造商：" + operatingSystem.getManufacturer());
        Console.log("操作系统位数：" + operatingSystem.getBitness());
        Console.log("当前运行的进程数：" + operatingSystem.getProcessCount());
        Console.log("当前运行的线程数：" + operatingSystem.getThreadCount());
        Console.log("系统已启动时间(秒)：" + operatingSystem.getSystemUptime());
        //获取cpu信息
        CpuInfo cpuInfo = OshiUtil.getCpuInfo();
        Console.log("CPU型号信息：" + cpuInfo.getCpuModel());
        Console.log("cpu核心数：" + cpuInfo.getCpuNum());
        Console.log("CPU总的使用率：" + cpuInfo.getToTal());
        Console.log("CPU当前空闲率：" + cpuInfo.getFree());
        Console.log("CPU系统使用率：" + cpuInfo.getSys());
        Console.log("CPU用户使用率：" + cpuInfo.getUsed());
        Console.log("CPU当前等待率：" + cpuInfo.getWait());
        Console.log("CPU当前等待率：" + cpuInfo.getWait());
        //内存
        GlobalMemory globalMemory = OshiUtil.getMemory();
        Console.log("总物理内存：" + globalMemory.getTotal());
        Console.log("可用物理内存：" + globalMemory.getAvailable());
        //获取磁盘相关信息，可能有多个磁盘（包括可移动磁盘等）
        List<HWDiskStore> hwDiskStoreList = OshiUtil.getDiskStores();
        Console.log("磁盘数：" + hwDiskStoreList.size());
        int index = 1;
        for (HWDiskStore hwDiskStore : hwDiskStoreList) {
            Console.log("磁盘" + index + "信息");
            Console.log("磁盘名称：" + hwDiskStore.getName());
            Console.log("磁盘型号：" + hwDiskStore.getModel());
            Console.log("磁盘序列号：" + hwDiskStore.getSerial());
            Console.log("磁盘大小：" + hwDiskStore.getSize());
            Console.log("磁盘读取的次数：" + hwDiskStore.getReads());
            Console.log("磁盘读取的字节数：" + hwDiskStore.getReadBytes());
            Console.log("磁盘写入的次数：" + hwDiskStore.getWrites());
            Console.log("磁盘写入的字节数：" + hwDiskStore.getWriteBytes());

            for (HWPartition hwPartition : hwDiskStore.getPartitions()) {
                Console.log("分区名字：" + hwPartition.getName());
                Console.log("分区型号：" + hwPartition.getType());
                Console.log("分区唯一标识符：" + hwPartition.getUuid());
                Console.log("分区大小：" + hwPartition.getSize());
                Console.log("分区大小：" + hwPartition.getMinor());
                Console.log("分区mountPoint：" + hwPartition.getMountPoint());
                Console.log("分区identification：" + hwPartition.getIdentification());
            }

            ++index;
        }

        getHardDisk();
        getSensors();
    }
}
